package com.lzw.breadknife;

import com.lzw.breadknife.bean.Bind;
import com.lzw.breadknife.bean.ElementsBean;
import com.lzw.breadknife.bean.Field;
import com.lzw.breadknife.bean.Immersive;
import com.lzw.breadknife.bean.Link;
import com.lzw.breadknife.bean.Method;
import com.lzw.breadknife.bean.View;
import com.lzw.breadknife.util.ClassUtil;
import com.lzw.breadknife.util.ClassValidator;
import com.lzw.breadknife.util.Logger;
import com.lzw.breadknife.util.StringUtil;
import com.lzw.breadknife.util.ViewCollection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;



public class ElementsHelper {

    public static final String TAG = ElementsHelper.class.getSimpleName();

    private Messager messager;

    public static final String PROXY = "Unbinder";
    private TypeElement typeElement;
    private String className;//MainActivity
    private String proxyClassName;//MainActivityUnbinder
    private String packageName;//package com.lzw.breadknife
    private ElementsBean elementsBean;
    private String javaSource;
    private String host;
    private List<String> imports = new ArrayList<>();
    private String packages;
    private String buidPath;

    // 存储注解所在类的包名
    ArrayList<String> packageNameList = new ArrayList<>();

    /**
     * 项目的根包名
     */
    private String rootPkg;

    /**
     * 获取项目的根包名
     * @return
     */
    public String getRootPkg() {
        return rootPkg;
    }

    /**
     * 设置项目的根包名
     * @param rootPkg
     */
    public void setRootPkg(String rootPkg) {
        this.rootPkg = rootPkg;
    }

    /**
     *
     * @param messager
     * @param elementUtils
     * @param classElement
     */
    public ElementsHelper(Messager messager, Elements elementUtils, TypeElement classElement) {
        this.messager = messager;
        this.typeElement = classElement;
        PackageElement packageElement = elementUtils.getPackageOf(classElement);
        String packageName = packageElement.getQualifiedName().toString();

        // 直接获取类名会报错：【错误: 找不到符号 XXXUnbinder】
        className = ClassValidator.getClassName(classElement, packageName);
        Logger.logInfo(messager, "原始类名= " + ClassValidator.getClassName(classElement, packageName));

//        try {
//            Class<?> aClass = Class.forName(packageName + "." + ClassValidator.getClassName(classElement, packageName));
//            Logger.logInfo(messager, "原始类名= " + ClassValidator.getClassName(classElement, packageName));
//            className = aClass.getName();
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }

        this.packageName = packageName;
        packageNameList.add(packageName);
        this.proxyClassName = className + PROXY;

    }

    public String getPackageName() {
        // 按字符串长度排序，最短的在前面
        Collections.sort(packageNameList, new Comparator<String>() {
            @Override
            public int compare(String pkg1, String pkg2) {
                return Integer.compare(pkg1.length(), pkg2.length());
            }
        });
        // 最短那个就是项目的根包名
        String pkgName = packageNameList.get(0);
        return pkgName;
    }

    private boolean isShowProxyClassFullName = false;

    private String fullName;

    public void setIsShowProxyClassFullName(boolean isShowProxyClassFullName) {
        this.isShowProxyClassFullName = isShowProxyClassFullName;
        if(isShowProxyClassFullName) { // 生成的Java文件类名
            this.fullName = this.packageName + "." + this.proxyClassName;
        } else { // 被注解的文件完整类名
            this.fullName = this.packageName + "." + this.className;
        }
    }

    public String getClassFullName() {
        return this.fullName;
    }

    public TypeElement getTypeElement() {
        return this.typeElement;
    }

    /**
     * fix: 生成Java代码不完整的问题
     * @param buidPath
     * @param packages
     * @param processingEnv
     * @param typeElement
     * @return
     */
    public String generateJavaCode(String buidPath, String packages, ProcessingEnvironment processingEnv, TypeElement typeElement) {
        if (ClassUtil.instanceOfActivity(className)) {
            host = "host.";
        } else {
            host = "view.";
        }
        this.packages = packages;
        this.buidPath = buidPath;
        javaSource = String.format(Constant.javaPath, buidPath, packageName.replace(".", "/"), className);

        elementsBean = new ElementsBean();

        // 解析类文件
        ClassParser.parser(processingEnv, javaSource, elementsBean, packageName + "." + className);
        // 解析xml文件
        XmlParser.parser(buidPath, elementsBean.getLayout(), elementsBean, processingEnv, typeElement);

        return Constant.unBinderStr
                .replaceAll(Constant.className, className)
                .replaceAll(Constant.iPackage, packageName)
                // fix: 修复R文件路径不准确的问题
                .replaceAll(Constant.iRootPackage, rootPkg)
                .replaceAll(Constant.proxy, proxyClassName)
                .replaceAll(Constant.packages, packages)
                .replaceAll(Constant.setContentView, generateContentView(processingEnv))
                .replaceAll(Constant.bindField, generateBindField(processingEnv))
                .replaceAll(Constant.iJavabean, generateIJavabean())
                .replaceAll(Constant.iView, generateIView())
                .replaceAll(Constant.javabean, generateJavabean())
                .replaceAll(Constant.view, generateView())
                .replaceAll(Constant.findView, generateFindView())
                .replaceAll(Constant.transfer, generateTransfer())
                .replaceAll(Constant.set, generateSetBean())
                .replaceAll(Constant.clear, generateClear())
                .replaceAll(Constant.clearAll, generateClearAll())
                .replaceAll(Constant.viewModel, generateViewModel())
                .replaceAll(Constant.notify, generateNotify())
                .replaceAll(Constant.iimport, generateImport());
    }

    private String generateBindField(ProcessingEnvironment processingEnv) {
        StringBuilder builder = new StringBuilder();
        if (!ClassUtil.instanceOfActivity(className)) {
            return builder.toString();
        }
        List<Field> bundles = elementsBean.getBundles();
        if (bundles.size() != 0) {
            for (Field bundle : bundles) {
                if (bundle.getRefrence() != null) {
                    String[] refs = bundle.getRefrence();
                    imports.addAll(Arrays.asList(refs));
                }
                if (bundle.getClassType().equals("int") || bundle.getClassType().equals("Integer")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getIntExtra(").append(bundle.getIds()[0]).append(", 0);");
                } else if (bundle.getClassType().equals("short") || bundle.getClassType().equals("Short")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getShortExtra(").append(bundle.getIds()[0]).append(", (short) 0);");
                } else if (bundle.getClassType().equals("long") || bundle.getClassType().equals("Long")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getLongExtra(").append(bundle.getIds()[0]).append(",0);");
                } else if (bundle.getClassType().equals("double") || bundle.getClassType().equals("Double")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getDoubleExtra(").append(bundle.getIds()[0]).append(",0);");
                } else if (bundle.getClassType().equals("float") || bundle.getClassType().equals("Float")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getFloatExtra(").append(bundle.getIds()[0]).append(",0);");
                } else if (bundle.getClassType().equals("char")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getCharExtra(").append(bundle.getIds()[0]).append(", (char) 0);");
                } else if (bundle.getClassType().equals("boolean") || bundle.getClassType().equals("Boolean")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getBooleanExtra(").append(bundle.getIds()[0]).append(", false);");
                } else if (bundle.getClassType().equals("String")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getStringExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("int")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getIntArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("short")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getShortArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("long")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getLongArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("double")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getDoubleArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("float")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getFloatArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("char")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getCharArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("boolean")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getBooleanArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[") && bundle.getClassType().contains("String")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getStringArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("List") && bundle.getClassType().contains("String")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getStringArrayListExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("List") && bundle.getClassType().contains("Integer")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getIntegerArrayListExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("List")) {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getParcelableArrayListExtra(").append(bundle.getIds()[0]).append(");");
                } else if (bundle.getClassType().contains("[")) {
                    if (bundle.getFullClass() != null)
                        imports.add(bundle.getFullClass());
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("(").append(bundle.getClassType()).append(") ").append("host.getIntent().");
                    builder.append("getParcelableArrayExtra(").append(bundle.getIds()[0]).append(");");
                } else {
                    builder.append("        host.").append(bundle.getVariable()).append(" = ").append("host.getIntent().");
                    builder.append("getParcelableExtra(").append(bundle.getIds()[0]).append(");");
                }
                builder.append("\n");
            }
        }
        return builder.toString();
    }

    private String generateImport() {
        StringBuilder builder = new StringBuilder();
        for (String s : imports) {
            if (!builder.toString().contains(s)) {
                builder.append("import ").append(s).append(";\n");
            }
        }
        String result = builder.toString();
        return result;
    }

    private String generateNotify() {
        List<Link> links = elementsBean.getLabel().getLinkes();
        if (links.size() == 0) return "";
        StringBuilder builder = new StringBuilder();
        builder.append("    @Override\n" +
                "    public void notifyDataChange(Class clazz) {\n" +
                "        if (clazz == null) {\n" +
                "        } ");
        for (Link link : links) {
            if (link.getAlisa().equalsIgnoreCase("viewModel"))
                continue;
            builder.append("else if (clazz == " + StringUtil.toUpperCase(link.getClassName()) + ".class) {\n" +
                    "            set" + StringUtil.toUpperCase(link.getAlisa()) + "(this." + link.getAlisa() + ");\n" +
                    "        }");
        }
        builder.append("\n    }\n");
        return builder.toString();
    }

    private String generateViewModel() {
        if (elementsBean.getLayout() == null) return "";
        List<Link> links = elementsBean.getLabel().getViewModels();
        if (links.size() == 0) return "";
        StringBuilder builder = new StringBuilder();
        builder.append("    @Override\n" +
                "    public void bindViewModels(Object viewModel) {\n");
        for (int i = 0; i < links.size(); i++) {
            if (i == 0)
                builder.append("        if (viewModel instanceof " + links.get(i).getClassName() + ")\n");
            else
                builder.append("        else if (viewModel instanceof " + links.get(i).getClassName() + ")\n");
            builder.append("            this." + links.get(i).getAlisa() + " = (" + links.get(i).getClassName() + ") viewModel;\n");
        }

        builder.append("    }\n");
        return builder.toString();
    }

    private String generateTransfer() {
        StringBuilder builder = new StringBuilder();
        List<Method> methods = elementsBean.getMethods();

        for (Method method : methods) {
            String[] ids = method.getIds();
            for (String id : ids) {
                builder.append("        " + host + "findViewById(" + id + ").setOnClickListener(new View.OnClickListener() {\n" +
                        "            @Override\n" +
                        "            public void onClick(View v) {\n" +
                        "                host." + method.getMethodName() + "(v);\n" +
                        "            }\n" +
                        "        });\n");
            }
        }
        if (elementsBean.getLayout() != null) {
            List<View> views = elementsBean.getLabel().getViews();
            List<Link> links = elementsBean.getLabel().getLinkes();
            for (View view : views) {
                Map<String, String> transfers = view.getTransfer();
                for (Map.Entry<String, String> entry : transfers.entrySet()) {
                    Map<String, String[]> map = StringUtil.clickChangeMethod(entry.getValue(), links, views);
                    String[] method = map.get(Constant.METHOD);
                    String[] protect = map.get(Constant.PROTECT);
                    if (method.length == 0) continue;
                    if (entry.getKey().endsWith(XmlParser.click)) {
                        generateClick(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.longclick)) {
                        generateLongClick(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.textChanged)) {
                        generateTextChange(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.tabSelected)) {
                        generateTabSelected(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.tabUnselected)) {
                        generateTabUnselected(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.pageSelected)) {
                        generatePageSelected(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.checkedChanged)) {
                        generateCheckChange(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.radioChanged)) {
                        generateRadioChanged(builder, view.getId(), method, protect);
                    } else if (entry.getKey().endsWith(XmlParser.progressChanged)) {
                        generateProgressChanged(builder, view.getId(), method, protect);
                    }
                }


            }
        }
        return builder.toString();
    }

    private void generateRadioChanged(StringBuilder builder, String id, String[] method, String[] protect) {
        imports.add("com.lzw.breadknife.OnRadioButtonCheckedChangeListener");
        builder.append("        " + id + ".setOnCheckedChangeListener(new OnRadioButtonCheckedChangeListener(" + id + ") {\n" +
                "            @Override\n" +
                "            public void onChecked(RadioGroup radioGroup, int id) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "radioGroup, id") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "radioGroup, id") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "radioGroup, id") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "radioGroup, id") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateProgressChanged(StringBuilder builder, String id, String[] method, String[] protect) {
        imports.add("com.lzw.breadknife.OnSeekBarChangeListener");
        imports.add("android.widget.SeekBar");
        builder.append("        " + id + ".setOnSeekBarChangeListener(new OnSeekBarChangeListener(){\n" +
                "            @Override\n" +
                "            public void onProgressChanged(SeekBar seekBar, State state, int progress, boolean fromUser) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "seekBar, state, progress, fromUser") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "seekBar, state, progress, fromUser") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "seekBar, state, progress, fromUser") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "seekBar, state, progress, fromUser") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateTabUnselected(StringBuilder builder, String id, String[] method, String[] protect) {
        builder.append("        " + id + ".addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {\n" +
                "            @Override\n" +
                "            public void onTabReselected(TabLayout.Tab tab) {\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onTabSelected(TabLayout.Tab tab) {\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onTabUnselected(TabLayout.Tab tab) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "tab") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "tab") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "tab") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "tab") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateTabSelected(StringBuilder builder, String id, String[] method, String[] protect) {
        builder.append("        " + id + ".addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {\n" +
                "            @Override\n" +
                "            public void onTabUnselected(TabLayout.Tab tab) {\n" +
                "\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onTabReselected(TabLayout.Tab tab) {\n" +
                "\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onTabSelected(TabLayout.Tab tab) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "tab") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "tab") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "tab") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "tab") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateCheckChange(StringBuilder builder, String id, String[] method, String[] protect) {
        imports.add("com.lzw.breadknife.OnCheckBoxCheckedChangeListener");
        imports.add("android.widget.CompoundButton");
        builder.append("        " + id + ".setOnCheckedChangeListener(new OnCheckBoxCheckedChangeListener() {\n" +
                "            @Override\n" +
                "            public void onChecked(CompoundButton compoundButton, boolean checked) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "checked") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "checked") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "checked") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "checked") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generatePageSelected(StringBuilder builder, String id, String[] method, String[] protect) {
        builder.append("        " + id + ".addOnPageChangeListener(new ViewPager.OnPageChangeListener() {\n" +
                "            @Override\n" +
                "            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n" +
                "                \n" +
                "            }\n" +
                "\n" +
                "\n" +
                "            @Override\n" +
                "            public void onPageScrollStateChanged(int state) {\n" +
                "\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onPageSelected(int position) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "position") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "position") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "position") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "position") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateTextChange(StringBuilder builder, String id, String[] method, String[] protect) {
        imports.add("com.lzw.breadknife.TextWatcher");
        builder.append("        " + id + ".addTextChangedListener(new TextWatcher() {\n" +
                "            @Override\n" +
                "            public void onTextChange(String content) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "content") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "content") + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + StringUtil.insertParamter(method[i], "content") + "\n");
                else
                    builder.append("                host." + StringUtil.insertParamter(method[i], "content") + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private void generateLongClick(StringBuilder builder, String id, String[] method, String[] protect) {
        builder.append("        " + id + ".setOnLongClickListener(new View.OnLongClickListener() {\n" +
                "            @Override\n" +
                "            public boolean onLongClick(View v) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + method[i] + "\n");
                else
                    builder.append("                host." + method[i] + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + method[i] + "\n");
                else
                    builder.append("                host." + method[i] + "\n");
            }
        }
        builder.append("                return true;\n" +
                "            }\n" +
                "        });\n");
    }

    private void generateClick(StringBuilder builder, String id, String[] method, String[] protect) {
        builder.append("        " + id + ".setOnClickListener(new View.OnClickListener() {\n" +
                "            @Override\n" +
                "            public void onClick(View v) {\n");
        for (int i = 0; i < method.length; i++) {
            if (protect[i].length() > 0) {
                builder.append("                if(" + protect[i] + ") {\n");
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + method[i] + "\n");
                else
                    builder.append("                host." + method[i] + "\n");
                builder.append("                }\n");
            } else {
                if (StringUtil.checkMethodHavePreffix(method[i]))
                    builder.append("                " + StringUtil.methodPreffixProtect(method[i]) + method[i] + "\n");
                else
                    builder.append("                host." + method[i] + "\n");
            }
        }
        builder.append("            }\n" +
                "        });\n");
    }

    private String generateFindView() {
        StringBuilder builder = new StringBuilder();
        List<Field> fields = elementsBean.getFileds();
        for (Field field : fields) {
            if (field.getIds().length == 1)
                builder.append("        host." + field.getVariable() + " = (" + field.getClassType() + ") " + host + "findViewById(" + field.getIds()[0] + ");\n");
            else {
                builder.append("        host." + field.getVariable() + " = new " + field.getClassType() + "{\n");
                String[] ids = field.getIds();
                for (int i = 0; i < ids.length; i++) {
                    builder.append("                (" + field.getClassName() + ") " + host + "findViewById(" + ids[i] + ")");
                    if (i == ids.length - 1)
                        builder.append("\n");
                    else
                        builder.append(",\n");
                }
                builder.append("        };\n");
            }
        }
        if (elementsBean.getLayout() != null) {
            List<View> views = elementsBean.getLabel().getViews();
            for (View view : views) {
                builder.append("        " + view.getId() + " = (" + view.getClassName() + ") " + host + "findViewById(R.id." + view.getId() + ");\n");
            }
        }
        return builder.toString();
    }

    private String generateClearAll() {
        String clear = generateClear();
        if (elementsBean.getLayout() == null) return clear;
        List<View> views = elementsBean.getLabel().getViews();
        List<Link> viewModels = elementsBean.getLabel().getViewModels();
        StringBuilder builder = new StringBuilder();
        builder.append(
                "    @Override\n" +
                        "    public void clearAll() {\n" +
                        "        super.clearAll();\n"
        );
        if (clear.length() > 3)
            builder.append("        this.clear();\n");
        for (View view : views) {
            builder.append("        this.").append(view.getId()).append(" = null;\n");
        }
        for (Link viewModel : viewModels) {
            builder.append("        this.").append(viewModel.getAlisa()).append(" = null;\n");
        }
        builder.append("    }\n\n");
        return builder.toString();

    }

    private String generateClear() {
        if (elementsBean.getLayout() == null) return "";
        List<Link> links = elementsBean.getLabel().getLinkes();
        if (links.size() == 0) return "";
        StringBuilder builder = new StringBuilder();
        builder.append(
                "    @Override\n" +
                        "    public void clear() {\n");
        for (Link link : links) {
            builder.append("        super.clearLiveData(" + link.getAlisa() + ");\n");
            builder.append("        this.").append(link.getAlisa()).append(" = null;\n");
        }
        builder.append("    }\n");
        return builder.toString();
    }

    private String generateView() {
        if (elementsBean.getLayout() == null) return "";
        List<View> views = elementsBean.getLabel().getViews();
        StringBuilder builder = new StringBuilder();
        for (View view : views) {
            builder.append("    public ").append(view.getClassName()).append(" ").append(view.getId()).append(";\n");
        }
        return builder.toString();
    }

    private String generateJavabean() {
        if (elementsBean.getLayout() == null) return "";
        List<Link> links = elementsBean.getLabel().getLinkes();
        StringBuilder builder = new StringBuilder();
        for (Link link : links) {
            builder.append("    public ").append(link.getClassName()).append(" ").append(link.getAlisa()).append(";\n");
        }
        links = elementsBean.getLabel().getViewModels();
        for (Link link : links) {
            builder.append("    private ").append(link.getClassName()).append(" ").append(link.getAlisa()).append(";\n");
        }
        return builder.toString();
    }

    private String generateIView() {
        StringBuilder builder = new StringBuilder();
        List<Field> fields = elementsBean.getFileds();
        for (Field field : fields) {
            String fullClassName = ViewCollection.getFullNameByName(field.getClassName());
            if (fullClassName.length() != 0 && (!StringUtil.stringContainString(builder, fullClassName)))
                builder.append("import ").append(fullClassName).append(";\n");
        }
        if (elementsBean.getLayout() != null) {
            List<View> views = elementsBean.getLabel().getViews();
            for (View view : views) {
                String fullClassName = view.getFullClassName();
                if (fullClassName.length() != 0 && (!StringUtil.stringContainString(builder, fullClassName)))
                    builder.append("import ").append(fullClassName).append(";\n");
            }
        }
        return builder.toString();
    }

    private String generateIJavabean() {
        if (elementsBean.getLayout() == null) return "";
        List<Link> links = elementsBean.getLabel().getLinkes();
        StringBuilder builder = new StringBuilder();
        for (Link link : links) {
            if (!StringUtil.stringContainString(builder, link.getFullClassName()))
                builder.append("import ").append(link.getFullClassName()).append(";\n");
        }
        links = elementsBean.getLabel().getViewModels();
        for (Link link : links) {
            if (!StringUtil.stringContainString(builder, link.getFullClassName()))
                builder.append("import ").append(link.getFullClassName()).append(";\n");
        }
        return builder.toString();
    }

    private String generateSetBean() {
        if (elementsBean.getLayout() == null) return "";
        List<Link> links = elementsBean.getLabel().getLinkes();
        StringBuilder builder = new StringBuilder();
        for (Link link : links) {
            if (link.getAlisa().equalsIgnoreCase("viewModel"))
                continue;
            builder.append("    public void set" + StringUtil.toUpperCase(link.getAlisa()) + "(" + StringUtil.toUpperCase(link.getClassName()) + " " + link.getAlisa() + ") {\n" +
                    "        if (" + link.getAlisa() + " == null) return;\n" +
                    "        this." + link.getAlisa() + " = " + "setEntity(this." + link.getAlisa() + ", " + link.getAlisa() + ");\n");
            List<View> views = elementsBean.getLabel().getViews();
            for (View view : views) {
                Bind bind = view.getBind();
                if (bind == null) continue;
                String[] methods = bind.getMethod(links);
                String[] protect = bind.getProtect(links);
                String[] alisas = bind.getAlisa(links);
                for (int i = 0; i < methods.length; i++) {
                    if (!alisas[i].equalsIgnoreCase(link.getAlisa())) continue;
                    if (protect[i].length() == 0) {
                        builder.append("        BreadKnifeInjector.injector(" + view.getId() + "," + methods[i] + ");\n");
                    } else {
                        builder.append("        if(" + protect[i] + ") {\n");
                        builder.append("            BreadKnifeInjector.injector(" + view.getId() + "," + methods[i] + ");\n");
                        builder.append("        }\n");
                    }
                }


            }
            builder.append("    }\n\n");
        }
        return builder.toString();
    }

    private String generateContentView(ProcessingEnvironment processingEnv) {
        if (ClassUtil.instanceOfActivity(className)) {
            if (elementsBean.getImmersive() != null && elementsBean.getLayout() != null) {

                ImmersiveInjector config = new ImmersiveInjector(processingEnv);
                config.writeCode(buidPath, packages);

                imports.add(packages + ".ImmersiveInjector");
                Immersive immersive = elementsBean.getImmersive();
                StringBuilder builder = new StringBuilder();
                builder.append("        super.bind(target, obj);\n");
                builder.append("        ImmersiveInjector.setContentView(host, R.layout.").append(elementsBean.getLayout()).append(", ");
                if (immersive.getStatusColor() != null) {
                    builder.append(immersive.getStatusColor()).append(",");
                } else {
                    imports.add(packages + ".ImmersiveInjector");
                    builder.append("ImmersiveInjector.statusColor(host)").append(",");
                }
                if (immersive.getNavigationColor() != null) {
                    builder.append(" ").append(immersive.getNavigationColor()).append(",");
                } else {
                    imports.add(packages + ".ImmersiveInjector");
                    builder.append(" ").append("ImmersiveInjector.navigationColor(host)").append(",");
                }
                if (immersive.getStatusEmbed() != null) {
                    builder.append(" ").append(immersive.getStatusEmbed()).append(",");
                } else {
                    imports.add(packages + ".ImmersiveInjector");
                    builder.append(" ").append("ImmersiveInjector.statusEmbed(host)").append(",");
                }
                if (immersive.getNavigationEmbed() != null) {
                    builder.append(" ").append(immersive.getNavigationEmbed()).append(");\n");
                } else {
                    imports.add(packages + ".ImmersiveInjector");
                    builder.append(" ").append("ImmersiveInjector.navigationEmbed(host)").append(");\n");
                }
                return builder.toString();
            } else if (elementsBean.getLayout() != null) // 如果没有开启沉浸式
                return "        super.bind(target, obj, R.layout." + elementsBean.getLayout() + ");\n";
            else
                return "        super.bind(target, obj);\n";
        } else { // 如果不是Activity
            if (elementsBean.getLayout() == null) {
                return "        super.bind(target, obj, LAYOUT_NULL);\n";
            }
            return "        super.bind(target, obj, R.layout." + elementsBean.getLayout() + ");\n";
        }
    }


}
